﻿using Microsoft.Data.Edm;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Metadata;
using System.Web.Http.Validation;
using WooCoo.ObjectModel;
using WooCoo.Tools;

namespace WooCoo.DataPortal.WebHost
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)]
    public class FromJsonBody : ParameterBindingAttribute
    {
        public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter)
        {
            if (parameter == null)
            {
                throw Error.ArgumentNull("parameter");
            }
            //IEnumerable<MediaTypeFormatter> formatters = parameter.Configuration.Formatters;
            //IBodyModelValidator bodyModelValidator = parameter.Configuration.Services.GetBodyModelValidator();
            //return parameter.BindWithFormatter(formatters, bodyModelValidator);
            return new FromJsonParameterBinding(parameter);
        }

        internal class FromJsonParameterBinding : HttpParameterBinding
        {
            public FromJsonParameterBinding(HttpParameterDescriptor parameterDescriptor)
                : base(parameterDescriptor)
            {

            }
            public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken)
            {
                if (actionContext == null)
                {
                    throw Error.ArgumentNull("actionContext");
                }

                HttpRequestMessage request = actionContext.Request;

                if (request == null)
                {
                    throw Error.Argument("ActionContextMustHaveRequest", "actionContext");
                }

                HttpActionDescriptor actionDescriptor = actionContext.ActionDescriptor;

                if (actionDescriptor == null)
                {
                    throw Error.Argument("ActionContextMustHaveDescriptor", "actionContext");
                }

                HttpConfiguration configuration = request.GetConfiguration();

                if (configuration == null)
                {
                    throw Error.Argument("RequestMustContainConfiguration", "actionContext");
                }

                object parameterValue;
                HttpContent content = request.Content;
                string jResult = content.ReadAsStringAsync().Result;
                if (actionDescriptor.ActionName.Equals("Excute", StringComparison.CurrentCultureIgnoreCase))
                {
                    parameterValue = Newtonsoft.Json.JsonConvert.DeserializeObject<ActionInfo>(jResult);
                }
                else
                {
                    IEdmModel model = request.GetEdmModel();
                    Type entityClrType = EdmLibHelpers.GetClrType(request.GetODataPath().EntitySet.ElementType, model);
                    //actionDescriptor.GetParameters()

                    if (jResult[0] == '[')
                    {
                        //List
                        parameterValue = Newtonsoft.Json.JsonConvert.DeserializeObject(jResult, typeof(EntityList<>).MakeGenericType(entityClrType));
                    }
                    else
                    {
                        parameterValue = Newtonsoft.Json.JsonConvert.DeserializeObject(jResult, entityClrType);
                    }
                }
                //ActionInfo parameterValue = Newtonsoft.Json.JsonConvert.DeserializeObject<ActionInfo>(json);

                SetValue(actionContext, parameterValue);

                return TaskHelpers.Completed();
            }

        }
    }
}
